﻿using System;
using System.Activities;
using System.Activities.Core.Presentation;
using System.Activities.Debugger;
using System.Activities.Presentation;
using System.Activities.Presentation.Debug;
using System.Activities.Presentation.Services;
using System.Activities.Tracking;
using System.Activities.XamlIntegration;
using System.Collections.Generic;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Threading;
using SLS.ExClassLib.DataType;
using SLS.ExClassLib.Events;
using SLS.ExClassLib.Message;
using SLS.ExClassLib.Data;
using SLS.ExClassLib.MVVM;
using SLS.ExClassLib.WFActivities;
namespace SLS.Base
{
    public partial class ExEDIT
    {
        #region==============PROPERTIES====================================
        Grid RehostGrid
        {
            get
            {
                return (Grid)FindName("RehostGrid");
            }
        }
        Grid TrackingRecord
        {
            get
            {
                return (Grid)FindName("TrackingRecord");
            }
        }
        public VisualTrackingParticipant Tracker;
        public WorkflowDesigner WorkflowDesigner { get; set; }
        public IDesignerDebugView DebuggerService { get; set; }

        public TextBox tx;
        public Dictionary<int, SourceLocation> textLineToSourceLocationMap;
        Dictionary<object, SourceLocation> wfElementToSourceLocationMap;
        Dictionary<string, Activity> activityIdToWfElementMap;
        public int i = 0;
        #endregion

        #region==============WFTracker====================================
        void AddTrackingTextbox()
        {
            tx = new TextBox();
            Grid.SetRow(tx, 1);

            Label trackRecords = new Label();
            trackRecords.FontSize = 11;
            trackRecords.FontWeight = FontWeights.Bold;
            trackRecords.Content = "Tracking Records: ";
            Grid.SetRow(trackRecords, 0);
            this.TrackingRecord.Children.Add(trackRecords);
            this.TrackingRecord.Children.Add(tx);

            //For Tracking Records displayed and to check which activity those records corresponds to.
            this.tx.SelectionChanged += new RoutedEventHandler(textBox1_SelectionChanged);
            textLineToSourceLocationMap = new Dictionary<int, SourceLocation>();

        }
        //Provide Debug Adornment on the Activity being executed
        void textBox1_SelectionChanged(object sender, RoutedEventArgs e)
        {

            string text = this.tx.Text;

            int index = 0;
            int lineClicked = 0;
            while (index < text.Length)
            {
                if (text[index] == '\n')
                    lineClicked++;
                if (this.tx.SelectionStart <= index)
                    break;

                index++;
            }


            this.Dispatcher.Invoke(DispatcherPriority.Normal, (Action)(() =>
            {
                try
                {
                    //Tell Debug Service that the Line Clicked is _______
                    this.WorkflowDesigner.DebugManagerView.CurrentLocation = textLineToSourceLocationMap[lineClicked];
                }
                catch (Exception)
                {
                    //If the user clicks other than on the tracking records themselves.
                    this.WorkflowDesigner.DebugManagerView.CurrentLocation = new SourceLocation(this.WorkflowXAML, 1, 1, 1, 10);
                }
            }));

        }
        private void AddWorkflowDesigner()
        {
            this.WorkflowDesigner = new WorkflowDesigner();

            this.DebuggerService = this.WorkflowDesigner.DebugManagerView;

            this.WorkflowDesigner.Load(WorkflowXAML);
            this.WorkflowDesigner.Flush();
            string text = WorkflowDesigner.Text;
            this.RehostGrid.Children.Add(this.WorkflowDesigner.View);

        }
        private void RegisterMetadata()
        {
            (new DesignerMetadata()).Register();
        }
        private Dictionary<string, Activity> BuildActivityIdToWfElementMap(Dictionary<object, SourceLocation> wfElementToSourceLocationMap)
        {
            Dictionary<string, Activity> map = new Dictionary<string, Activity>();

            Activity wfElement;
            foreach (object instance in wfElementToSourceLocationMap.Keys)
            {
                wfElement = instance as Activity;
                if (wfElement != null)
                {
                    map.Add(wfElement.Id, wfElement);
                }
            }

            return map;
        }
        void simTracker_TrackingRecordReceived(object sender, TrackingEventArgs e)
        {

            if (e.Activity != null)
            {  
                Application.Current.Dispatcher.Invoke(DispatcherPriority.SystemIdle, (Action)(() =>
                {
                    //Textbox Updates
                    tx.AppendText(e.Activity.DisplayName + " " + ((ActivityStateRecord)e.Record).State + "\n");
                    tx.AppendText("******************\n");
                    textLineToSourceLocationMap.Add(i, wfElementToSourceLocationMap[e.Activity]);
                    i = i + 2;

                    //Add a sleep so that the debug adornments are visible to the user
                   
                }
                ));
            }
        } 
        Dictionary<object, SourceLocation> UpdateSourceLocationMappingInDebuggerService()
        {
            object rootInstance = GetRootInstance();
            Dictionary<object, SourceLocation> sourceLocationMapping = new Dictionary<object, SourceLocation>();
            Dictionary<object, SourceLocation> designerSourceLocationMapping = new Dictionary<object, SourceLocation>();

            if (rootInstance != null)
            {
                Activity documentRootElement = GetRootWorkflowElement(rootInstance);
                SourceLocationProvider.CollectMapping(GetRootRuntimeWorkflowElement(), documentRootElement, sourceLocationMapping,
                    WorkflowDesigner.Context.Items.GetValue<WorkflowFileItem>().LoadedFile);
                SourceLocationProvider.CollectMapping(documentRootElement, documentRootElement, designerSourceLocationMapping,
                   WorkflowDesigner.Context.Items.GetValue<WorkflowFileItem>().LoadedFile);

            }

            // Notify the DebuggerService of the new sourceLocationMapping.
            // When rootInstance == null, it'll just reset the mapping.
            //DebuggerService debuggerService = debuggerService as DebuggerService;
            if (DebuggerService != null)
            {
                ((DebuggerService)DebuggerService).UpdateSourceLocations(designerSourceLocationMapping);
            }

            return sourceLocationMapping;
        }
        object GetRootInstance()
        {
            ModelService modelService = WorkflowDesigner.Context.Services.GetService<ModelService>();
            if (modelService != null)
            {
                return modelService.Root.GetCurrentValue();
            }
            else
            {
                return null;
            }
        }
        // Get root WorkflowElement.  Currently only handle when the object is ActivitySchemaType or WorkflowElement.
        // May return null if it does not know how to get the root activity.
        Activity GetRootWorkflowElement(object rootModelObject)
        {
            System.Diagnostics.Debug.Assert(rootModelObject != null, "Cannot pass null as rootModelObject");

            Activity rootWorkflowElement;
            IDebuggableWorkflowTree debuggableWorkflowTree = rootModelObject as IDebuggableWorkflowTree;
            if (debuggableWorkflowTree != null)
            {
                rootWorkflowElement = debuggableWorkflowTree.GetWorkflowRoot();
            }
            else // Loose xaml case.
            {
                rootWorkflowElement = rootModelObject as Activity;
            }
            return rootWorkflowElement;
        }

        Activity GetRootRuntimeWorkflowElement()
        {
            Activity root = ActivityXamlServices.Load(WorkflowXAML);
            WorkflowInspectionServices.CacheMetadata(root);

            IEnumerator<Activity> enumerator1 = WorkflowInspectionServices.GetActivities(root).GetEnumerator();
            //Get the first child of the x:class
            enumerator1.MoveNext();
            root = enumerator1.Current;
            return root;
        }
        #endregion

        public override void ProcessWFMessage(MessageEx msg)
        {
            base.ProcessWFMessage(msg);
            string JobID = msg.JobID;
            switch (JobID)
            {
                case "OnAwaitMachineJoin":
                    this.ViewDataSet.ExecuteMachineReady(true);
                    break;
                case "OnStartQueryUI":
                    //this.m_expQueryCond.IsExpanded = true;
                    //this.OnStartQueryUI(msg);
                    break; 
                case "OnSendJobForProcessing":
                    this.ViewDataSet.ExecuteAssignNewJob(msg, false);
                    break;
                case "OnAwaitChecking":
                    switch (msg.JobContent)
                    {
                        case "CheckFK109_CustomerType_MainKey":
                            this.ViewDataSet.ExecuteQualityCheck(true);
                            break;
                        case "CheckFK199_CustomerType_MainKey":
                            this.ViewDataSet.ExecuteQualityCheck(true);
                            break;
                        case "CheckFK299_CustomerType_MainKey":
                            this.ViewDataSet.ExecuteQualityCheck(true);
                            break;
                        default:
                            break;
                    }
                    break;
                case "OnSingleReturn":
                    AppendRecord(msg);
                    break;
                default:
                    break;
            }
            /*
            MessageEx msgN = new MessageEx(Address, "WFFederation", "OnGetNextMessage", "NO");
            msgN.TimeStamp = DateTime.Now;
            msgN.JobType = "WF2UI";
            EventDispatcher.Instance.POSTWFMessage(msgN, null, "OnGetNextMessage");
            //  EventDispatcher.Instance.POSTUI2WFMessage(msgN);
            */
        }
         
        public override void CMDEXE_TextChanged(object sender, TextChangedEventArgs e)
        {
            try
            { 
                base.CMDEXE_TextChanged(sender, e);
            }
            catch (Exception ex)
            {
                throw;
            }

        }
        public override ExDataRow commandNew(string SM, string KEYDEFTYPE, string GTPRE, string GTKEY, string KEYINSTANCETABLE)
        {
            ExDataRow row = null;
            try
            {
                row = base.commandNew(SM, KEYDEFTYPE, GTPRE, GTKEY, KEYINSTANCETABLE);
            }
            catch (Exception ex)
            {
                throw;
            }
            return row;
        }
        public override ExDataRow commandCopy(ExDataRow dwThis)
        {
            ExDataRow row = null;
            try
            {
                row = base.commandCopy(dwThis);
            }
            catch (Exception ex)
            {
                throw;
            }
            return row;
        }
        public override void commandDelete(ExDataRow dwThis)
        {
            try
            {
                base.commandDelete(dwThis);
            }
            catch (Exception ex)
            {
                throw;
            }
        }
        public override void commandModify(ExDataRow dwThis)
        {
            try
            {
                base.commandModify(dwThis);
            }
            catch (Exception ex)
            {
                throw;
            }
        }
        public override void commandInformation(ExDataRow dwThis)
        {
            try
            {
                base.commandInformation(dwThis);
            }
            catch (Exception ex)
            {
                throw;
            }
        }
        public override void commandSave(ExDataRow dwThis)
        {
            try
            {
                dwThis.OnSaveRecord(1); 
            }
            catch (Exception ex)
            {
                throw;
            }
        }
    }
}